package com.smartum.mpr.services;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;

import javax.imageio.ImageIO;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.smartum.mpr.business.NewsBusiness;
import com.smartum.mpr.business.NewsImageBusiness;
import com.smartum.mpr.business.UserBusiness;
import com.smartum.mpr.exception.NotExistsItemException;
import com.smartum.mpr.exception.NotExistsNewsException;
import com.smartum.mpr.model.Item;
import com.smartum.mpr.model.ItemImage;
import com.smartum.mpr.model.News;
import com.smartum.mpr.model.NewsImage;
import com.smartum.mpr.model.User;
import com.smartum.mpr.store.local.ItemImageProvider;
import com.smartum.mpr.store.local.NewsImageStoreProvider;
import com.smartum.mpr.util.BackendConfig;
import com.smartum.mpr.utils.ImageUtil;

@Controller
@RequestMapping("/news")
public class NewsService extends BaseService<News> {

	@Autowired
	NewsBusiness newsBusiness;
	@Autowired
	NewsImageBusiness imageBusiness;
	@Autowired
	UserBusiness userBusiness;

	@RequestMapping(method = RequestMethod.POST, value = "/get/all")
	public ResponseEntity<String> getAllNews(@RequestBody String json) {
		LOGGER_API.info("request: get all news - " + json);
		try {
			checkRequestPermissions(json);

			String request = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);
			Long timestamp = requestNode.get("timestamp").asLong();
			int amount = requestNode.get("amount").asInt();

			List<News> news = newsBusiness.getPublicNews(timestamp, amount);

			
			
			ObjectNode node = getTargetParser().getMapper().createObjectNode();
			node.put("news_count", newsBusiness.getNewsCount());
			node.put("news", getTargetParser().getMapper().valueToTree(news));
			
			ResponseEntity<String> response = getResponseInJsonType(
			        generateSuccessJson(mapper.writeValueAsString(node)), HttpStatus.OK);
			
			LOGGER_API.info("response : get all news - OK");
			logResponse(response);
			return response;
		} catch (Exception e) {
			LOGGER_API.error("response: get all news", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/get/one")
	public ResponseEntity<String> getOneNewsById(@RequestBody String json) {
		LOGGER_API.info("requrst: get news by id -" + json);
		try {
			checkRequestPermissions(json);

			String requestJsonBody = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();
			String newsIdText = mapper.readTree(requestJsonBody).get("news_id").asText();

			News news = newsBusiness.getNewsById(Long.parseLong(newsIdText));
			ResponseEntity<String> response = getResponseInJsonType(
			        generateSuccessJson(getTargetParser().writeEntity(news)), HttpStatus.OK);
			LOGGER_API.info("response : get news by id - OK");
			logResponse(response);
			return response;
		} catch (Exception e) {
			LOGGER_API.error("response : get news by id", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/delete")
	public ResponseEntity<String> removeNewsById(@RequestBody String json) {
		LOGGER_API.info("request: remove news - " + json);
		try {
			String token = extractTokenStringData(json);

			String requestJsonBody = extractRequestStringData(json);

			ObjectMapper mapper = getTargetParser().getMapper();
			String newsIdText = mapper.readTree(requestJsonBody).get("news_id").asText();

			News news = newsBusiness.getNewsById(Long.parseLong(newsIdText));
			if (news != null && news.getImage() != null) {
				(new NewsImageStoreProvider()).deleteImage(Long.parseLong(newsIdText));
			}

			newsBusiness.removeNewsById(token, Long.parseLong(newsIdText));
			LOGGER_API.info("response : remove news  by id - OK");
			return new ResponseEntity<String>(HttpStatus.OK);
		} catch (Exception e) {
			LOGGER_API.error("response : remove news by id", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/post")
	public ResponseEntity<String> addNews(@RequestParam(value = "json") String json,
	        @RequestParam(value = "photo") MultipartFile file) {
		LOGGER_API.info("request: add news - " + json);
		LOGGER_API.info("request: add news - file name" + file.getOriginalFilename());
		LOGGER_API.info("request: add news - file size" + file.getSize());
		try {
			String token = extractTokenStringData(json);
			String requestJson = extractRequestStringData(json);
			String appFolderPath = BackendConfig.getInstance().getAppFolder();
			News news = getTargetParser().parseEntity(requestJson);
			newsBusiness.saveNews(token, news);

			Long id = news.getId();
			String filePath = (new NewsImageStoreProvider()).storeImage(file, id);
			File imageFile = new File(appFolderPath + filePath);
			BufferedImage littleImage = ImageUtil.resizeImage(imageFile, 200, 200);
			String smallImagePath = ImageUtil.addPostfixToPhotoWithSupportFileFormat(filePath, "small");
			File smallPhotoFile = new File(appFolderPath + smallImagePath);
			ImageIO.write(littleImage, ImageUtil.getImageFormat(smallImagePath), smallPhotoFile);

			NewsImage image = new NewsImage();
			image.setLittleImagePath(smallImagePath);
			image.setImagePath(filePath);
			image.setId(id);
			image.setImageTimestamp(System.currentTimeMillis());
			imageBusiness.addImage(token, image);

			news.setImage(image);
			newsBusiness.saveNews(token, news);
			LOGGER_API.info("response : add news   - OK");
			return new ResponseEntity<String>(HttpStatus.OK);
		} catch (Exception e) {
			LOGGER_API.error("response : add news ", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/update/model")
	public ResponseEntity<String> update(@RequestBody String json) {
		LOGGER_API.info("request: update news - " + json);
		try {
			String token = extractTokenStringData(json);
			String requestJson = extractRequestStringData(json);

			ObjectMapper mapper = getTargetParser().getMapper();

			JsonNode requestNode = mapper.readTree(requestJson);

			Long newsId = requestNode.get("news_id").asLong();
			News news = newsBusiness.getNewsById(newsId);

			if(news==null){
				throw new NotExistsNewsException();
			}
			
			if (requestNode.get("news_title") != null) {
				news.setTitle(requestNode.get("news_title").asText());
			}
			if (requestNode.get("news_text") != null) {
				news.setText(requestNode.get("news_text").asText());
			}
			newsBusiness.updateNews(token, news);
			LOGGER_API.info("response : update news   - OK");
			return new ResponseEntity<String>(HttpStatus.OK);
		} catch (Exception e) {
			LOGGER_API.error("response : update news ", e);
			return handleException(e);
		}
	}

	
	@RequestMapping(value = "/update/photo", method = RequestMethod.POST)
	public ResponseEntity<String> updateImage(@RequestParam("json") String json, @RequestParam("photo") MultipartFile photo) {
		LOGGER_API.info("request: update news image - " + json);
		try {
			
			String token = extractTokenStringData(json);
			userBusiness.getUserByToken(token);
			String request = extractRequestStringData(json);
			
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);
			Long newsId = requestNode.get("news_id").asLong();

			News news = newsBusiness.getNewsById(newsId);
			if(news==null){
				throw new NotExistsNewsException();
			}
			
			String appFolderPath = BackendConfig.getInstance().getAppFolder();
			
			new NewsImageStoreProvider().deleteImage(newsId);
			String newsImageFilePath = (new NewsImageStoreProvider()).storeImage(photo, newsId);
			File imageFile = new File(appFolderPath + newsImageFilePath);
			BufferedImage littleImage = ImageUtil.resizeImage(imageFile, 200, 200);
			String smallImagePath = ImageUtil.addPostfixToPhotoWithSupportFileFormat(newsImageFilePath, "small");
			File smallPhotoFile = new File(appFolderPath + smallImagePath);
			ImageIO.write(littleImage, ImageUtil.getImageFormat(smallImagePath), smallPhotoFile);

			NewsImage image = new NewsImage();
			image.setLittleImagePath(smallImagePath);
			image.setImagePath(newsImageFilePath);
			image.setId(newsId);
			image.setImageTimestamp(System.currentTimeMillis());
			imageBusiness.addImage(token, image);

			news.setImage(image);
			newsBusiness.saveNews(token, news);

			LOGGER_API.info("request: update news image  - OK");
			return new ResponseEntity<String>(HttpStatus.OK);
		} catch (Exception e) {
			LOGGER_API.error("request: update news image ", e);
			return handleException(e);
		}

	}
	
	@Override
	protected Class<News> getEntityClass() {
		return News.class;
	}

}
